// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package resource

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"code.geniusai.org/notebook-manager/pkg/entity"
)

type JsonResult struct {
	Usage string     `json:"usage"`
	Sum   int64      `json:"sum"`
	Pvc   string     `json:"pvc"`
	List  []JsonData `json:"list"`
}

type JsonData struct {
	X string `json:"x"`
	Y string `json:"y"`
}

type RespPointResult struct {
	Status string `json:"status"`
	Data   struct {
		ResultType string `json:"resultType"`
		Result     []struct {
			Metric struct {
				Name        string `json:"__name__"`
				Container   string `json:"container"`
				Endpoint    string `json:"endpoint"`
				ID          string `json:"id"`
				Image       string `json:"image"`
				Instance    string `json:"instance"`
				Job         string `json:"job"`
				MetricsPath string `json:"metrics_path"`
				Name0       string `json:"name"`
				Namespace   string `json:"namespace"`
				Node        string `json:"node"`
				Pod         string `json:"pod"`
				Service     string `json:"service"`
			} `json:"metric"`
			Value []interface{} `json:"value"`
		} `json:"result"`
	} `json:"data"`
}

type RespResult struct {
	Status string `json:"status"`
	Data   struct {
		ResultType string `json:"resultType"`
		Result     []struct {
			Metric struct {
				Name        string `json:"__name__"`
				Container   string `json:"container"`
				Endpoint    string `json:"endpoint"`
				ID          string `json:"id"`
				Image       string `json:"image"`
				Instance    string `json:"instance"`
				Job         string `json:"job"`
				MetricsPath string `json:"metrics_path"`
				Name0       string `json:"name"`
				Namespace   string `json:"namespace"`
				Node        string `json:"node"`
				Pod         string `json:"pod"`
				Service     string `json:"service"`
			} `json:"metric"`
			Values [][]interface{} `json:"values"`
		} `json:"result"`
	} `json:"data"`
}

func (m *Manager) GetUsage(monitorReq *entity.MonitorReq, usageType string) (result *JsonResult, err error) {
	timeUnit := monitorReq.TimeUnit
	id := monitorReq.ID
	notebook, err := m.notebookStore.GetNotebook(id)
	if err != nil {
		return nil, entity.NewErrorf(entity.CodeParamInvalid, entity.MsgNotebookNotExisted, id)
	}
	currentTime := time.Now()
	thirtyMinutesAgoDr, err := time.ParseDuration("-30m")
	oneHoursAgoDr, err := time.ParseDuration("-1h")
	threeHoursAgoDr, err := time.ParseDuration("-3h")

	thirtyMinutesAgo := currentTime.Add(thirtyMinutesAgoDr)
	oneHoursAgo := currentTime.Add(oneHoursAgoDr)
	threeHoursAgo := currentTime.Add(threeHoursAgoDr)

	//notebook := &entity.Notebook{ID: "add_vgpux_add_c68b1afd-8bff-11ed-8a89-8e19c5df80bd", UserID: "add", Name: "vgpux", ProjectID: "add_c68b1afd-8bff-11ed-8a89-8e19c5df80bd"}
	//notebook.VGpuMemory = 12
	//notebook := &entity.Notebook{ID: "add_err_add_10057f9a-8c17-11ed-b16e-62e509eeda38", UserID: "add", Name: "err", ProjectID: "add_10057f9a-8c17-11ed-b16e-62e509eeda38"}

	startTime := thirtyMinutesAgo.Unix()
	endTime := currentTime.Unix()
	thirtyMinutesAgoStep := 30
	oneHoursAgoStep := 30
	threeHoursAgoStep := 30

	graphUrl := monitorReq.GraphUrl
	if usageType == "cpu" || usageType == "memory" {
		monitorReq.GraphParams.Set("query", fmt.Sprintf(monitorReq.GraphParams.Get("query"), notebook.UserID, notebook.Name, notebook.Name))
	}
	if usageType == "vGpu" || usageType == "ratio" {
		monitorReq.GraphParams.Set("query", fmt.Sprintf(monitorReq.GraphParams.Get("query"), notebook.Name, notebook.ProjectID))
	}
	if timeUnit == "lastHalfHours" {
		startTime = thirtyMinutesAgo.Unix()
		monitorReq.GraphParams.Add("start", fmt.Sprintf("%d", startTime))
		monitorReq.GraphParams.Add("end", fmt.Sprintf("%d", endTime))
		monitorReq.GraphParams.Add("step", fmt.Sprintf("%d", thirtyMinutesAgoStep))
	} else if timeUnit == "lastOneHours" {
		startTime = oneHoursAgo.Unix()
		monitorReq.GraphParams.Add("start", fmt.Sprintf("%d", startTime))
		monitorReq.GraphParams.Add("end", fmt.Sprintf("%d", endTime))
		monitorReq.GraphParams.Add("step", fmt.Sprintf("%d", oneHoursAgoStep))
	} else if timeUnit == "lastThreeHours" {
		startTime = threeHoursAgo.Unix()
		monitorReq.GraphParams.Add("start", fmt.Sprintf("%d", startTime))
		monitorReq.GraphParams.Add("end", fmt.Sprintf("%d", endTime))
		monitorReq.GraphParams.Add("step", fmt.Sprintf("%d", threeHoursAgoStep))
	}

	graphUrl = graphUrl + monitorReq.GraphParams.Encode()
	println("graphUrl：" + graphUrl)
	resp, err :=
		http.Get(graphUrl)

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	var resResult RespResult
	err = json.Unmarshal([]byte(string(body)), &resResult)
	if err != nil {
		fmt.Println(err.Error())
	}

	res := &JsonResult{}
	res.List = []JsonData{} // 定义数组
	res.Usage = ""
	if len(resResult.Data.Result) != 0 {
		graphPoint := resResult.Data.Result[0].Values
		for _, data := range graphPoint { // 循环赋值
			var dataOne JsonData
			dataOne.X = fmt.Sprintf("%.0f", data[0])
			dataOne.Y = fmt.Sprintf("%s", data[1])
			Y, err := strconv.ParseFloat(dataOne.Y, 64)
			if err == nil {
				dataOne.Y = fmt.Sprintf("%.2f", Y)
			}
			res.List = append(res.List, dataOne) // 数组append给值
		}
	}

	if err != nil {
		fmt.Println(err)
		fmt.Println(resp)
	}

	pointUrl := monitorReq.PointUrl
	monitorReq.PointParams.Add("time", fmt.Sprintf("%d", endTime))
	if usageType == "cpu" {
		monitorReq.PointParams.Set("query", fmt.Sprintf(monitorReq.PointParams.Get("query"), notebook.UserID, notebook.Name, notebook.Name, notebook.UserID, notebook.Name, notebook.Name, notebook.UserID, notebook.Name, notebook.Name))
	}
	if usageType == "memory" {
		monitorReq.PointParams.Set("query", fmt.Sprintf(monitorReq.PointParams.Get("query"), notebook.UserID, notebook.Name, notebook.Name))
	}
	if usageType == "vGpu" || usageType == "ratio" {
		monitorReq.PointParams.Set("query", fmt.Sprintf(monitorReq.PointParams.Get("query"), notebook.Name, notebook.ProjectID))
	}
	pointUrl = pointUrl + monitorReq.PointParams.Encode()
	println("pointUrl：" + pointUrl)

	// 获取占用值
	resp, err =
		http.Get(pointUrl)

	defer resp.Body.Close()
	body, err = ioutil.ReadAll(resp.Body)

	var resPointResult RespPointResult
	err = json.Unmarshal([]byte(string(body)), &resPointResult)
	if err != nil {
		fmt.Println(err.Error())
	}
	if len(resPointResult.Data.Result) > 0 && len(resPointResult.Data.Result[0].Value) > 0 {
		res.Usage = fmt.Sprintf("%s", resPointResult.Data.Result[0].Value[1])
	}

	// 添加默认值
	if res.Usage == "" {
		res.Usage = "0"
	}

	if usageType == "cpu" {
		cpuUsage, err := strconv.ParseFloat(res.Usage, 64)
		if err == nil {
			res.Usage = fmt.Sprintf("%.2f", cpuUsage) + "%"
		}
	}

	if usageType == "memory" {
		memoryUsage, err := strconv.ParseFloat(res.Usage, 64)
		if err == nil {
			res.Usage = fmt.Sprintf("%.2f", memoryUsage)
		}
		res.Sum = notebook.MemorySize
	}
	if usageType == "vGpu" {
		vGpuUsage, err := strconv.ParseFloat(res.Usage, 64)
		if err == nil {
			res.Usage = fmt.Sprintf("%.2f", vGpuUsage)
		}
		res.Sum = notebook.VGpuMemory
	}

	if usageType == "ratio" {
		ratioUsage, err := strconv.ParseFloat(res.Usage, 64)
		if err == nil {
			res.Usage = fmt.Sprintf("%.0f", ratioUsage) + "%"
		}
	}

	return res, nil
}

func (m *Manager) GetPvcUsage(monitorReq *entity.MonitorReq) (result *JsonResult, err error) {
	notebook, err := m.notebookStore.GetNotebook(monitorReq.ID)
	pvc, err := m.pvcStore.GetUserPvcByName(notebook.VolumeName, notebook.UserID)
	println(fmt.Sprintf("pvc为：Name=%s，Size=%d", pvc.Name, pvc.Size))

	res := &JsonResult{}

	println(fmt.Sprintf("pvc查询参数为：VolumeName=%s，UserID=%s", notebook.VolumeName, notebook.UserID))

	if err != nil {
		return nil, entity.NewErrorf(entity.CodeParamInvalid, entity.MsgNotebookNotExisted, monitorReq.ID)
	}

	//notebook := &entity.Notebook{ID: "geniusdemo_trrt_geniusdemo_33e55697-7f69-11ed-8c69-a6b883c9c488", UserID: "add", Name: "vgpu", ProjectID: "geniusdemo_33e55697-7f69-11ed-8c69-a6b883c9c488"}

	client := http.Client{Timeout: 1 * time.Second}
	resp, err :=
		client.Get(monitorReq.PointUrl + "?namespace=" + notebook.UserID + "&notebookName=" + notebook.Name)

	// 请求超时的处理逻辑
	if resp == nil {
		println("resp请求超时的处理逻辑...")
		res.Sum = pvc.Size
		res.Pvc = notebook.VolumeName
		res.Usage = "-"
		return res, nil
	}
	if resp.Body == nil {
		println("resp.Body请求超时的处理逻辑...")
		res.Sum = pvc.Size
		res.Pvc = notebook.VolumeName
		res.Usage = "-"
		return res, nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	println("string(body)：" + string(body))
	pvcFloat, err := strconv.ParseFloat(string(body), 64)

	pvcByGi := 0.00
	if err == nil {
		pvcByGi = pvcFloat / 1024.00 / 1024.00
	}

	res.Usage = fmt.Sprintf("%.2f", pvcByGi)
	println(fmt.Sprintf("WorkspaceSize的大小为：%d", notebook.WorkspaceSize))
	println(fmt.Sprintf("notebookname为：%s", notebook.Name))
	res.Sum = pvc.Size
	res.Pvc = notebook.VolumeName
	return res, nil
}
